package com.star.batchhandler.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;

import javax.sql.DataSource;

public class SQLCommandScheduler0 implements Runnable {

//	public static long executeTime = 0;
//	private long sycTime = 0;
	private Connection conn;
	Statement stmt;
	private volatile int currentJobs;
//	private volatile int readyJobs;
//	private Object readyLock = new Object();
	private int[] batchResults;
	// private ConcurrentHashMap<Command, Statement> stmts = new
	// ConcurrentHashMap<Command, Statement>();
	// private List<Thread> ts = new ArrayList<Thread>();
	// private ConcurrentHashMap<Command, Integer> batchResults = new
	// ConcurrentHashMap<Command, Integer>();
	private ArrayList<Command> commands = new ArrayList<Command>();
	private ArrayList<Command> backup_commands = new ArrayList<Command>();
	private boolean isFinished = false;

	private Thread addJobThread;

	public SQLCommandScheduler0() {
		// TODO Auto-generated constructor stub
	}
	public SQLCommandScheduler0(DataSource ds, Thread addJobThread) throws SQLException {
//		this.ds = ds;
		this.addJobThread = addJobThread;
		conn = ds.getConnection();
		conn.setAutoCommit(false);
	}

	@Override
	public void run() {

	}

	// public void addCurrentThread(Thread t) {
	// this.ts.add(t);
	// }

	public void addCommand(Command cmd) throws Exception {
//		System.out.println("add 1");
//		synchronized (readyLock) {
////			System.out.println("add 2");
//			readyJobs++;
//			if (isReady(readyJobs)) {
//				commands.clear();
//				readyJobs = 0;
//				readyLock.notifyAll();
//			} else {
//				readyLock.wait();
//			}
//		}
//		System.out.println("add 3");
		synchronized (this) {
//			System.out.println("add 4");
//			long begin = System.nanoTime();
			if (cmd.getParams() == null) {
				if (stmt == null) {
					stmt = conn.createStatement();
				}
				stmt.addBatch(cmd.getSql());
				// stmts.put(cmd, stmt);
			} else {
				if (stmt == null) {
					stmt = conn.prepareStatement(cmd.getSql());
				}
				((PreparedStatement) stmt).setLong(1, (Long) cmd.getParams()[0]);
				((PreparedStatement) stmt).addBatch();
				// stmts.put(cmd, ps);
			}
			commands.add(cmd);
			currentJobs++;
//			AbstractJob.consumTime += (System.nanoTime() - begin);
//			System.out.println("add 5.currentJobs:"+currentJobs);
			if (currentJobs == SQLBatchOperation.jobsInBatch) {
//				System.out.println("add 6.");
				batch();
			} else {
				this.wait();
			}
		}
	}

	public void batch() throws Exception {
		// for (Command cmd : stmts.keySet()) {
		// Statement stmt = stmts.remove(cmd);
		// batchResults.put(cmd, stmt.executeBatch());
		// stmt.close();
		// }
//		System.out.println("add 7.");
//		long begin = System.nanoTime();
		batchResults = stmt.executeBatch();
//		System.out.println("add 8.");
		conn.commit();
//		System.out.println("add 9.");
		stmt.close();
		recover();
//		executeTime += (System.nanoTime() - begin);
		synchronized (this) {
//			System.out.println("add 10.");
			this.notifyAll();
		}
	}

	private void recover() {
		backup_commands.clear();
		backup_commands.addAll(commands);
		commands.clear();
		currentJobs = 0;
		stmt = null;
	}

	private boolean isReady(int jobs) {
		return jobs == SQLBatchOperation.jobsInBatch;
	}

	public int getBatchResult(Command cmd) {
		return batchResults[backup_commands.indexOf(cmd)];
	}

	public boolean isFinished() {
		return isFinished;
	}

	public void setFinished() {
//		System.out.println("batch jobs finished!");
		synchronized (addJobThread) {
//			System.out.println("next batch notify!");
			addJobThread.notify();
		}
	}

}
